package owg.util.editor2d;

import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.WindowEvent;

import javax.swing.AbstractAction;
import javax.swing.BoxLayout;
import javax.swing.JLabel;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButtonMenuItem;

import owg.util.awt.EnumEditor;
import owg.util.awt.StringFormattedEditor;
import owg.util.editor2d.Editor2D.Axes;
import owg.util.editor2d.modes.BoxSelect;
import owg.util.editor2d.modes.BoxSelect.BoxSelectMode;
import owg.util.editor2d.modes.Mode;
import owg.util.editor2d.modes.Paint;
import owg.util.editor2d.modes.Rotate;
import owg.util.editor2d.modes.Scale;
import owg.util.editor2d.modes.Scale.ScaleMode;
import owg.util.editor2d.modes.Translate;

public class Editor2DMenuBar extends JMenuBar
{
	private Editor2DUI editorUI;
	private JMenu fileMenu, editMenu, modeMenu;
	
	private JRadioButtonMenuItem paintMode, boxSelectMode, circleSelectMode, paintSelectMode, 
		translateMode, translateXMode, translateYMode, translateLocalXMode, translateLocalYMode, 
		rotateMode, rotateIndividuallyMode, scaleMode;

	public Editor2DMenuBar(Editor2DUI editor2dui)
	{
		this.editorUI = editor2dui;
		fileMenu = new JMenu("File");

		fileMenu.add(new AbstractAction("New[ctrl-N]")
		{
			private static final long serialVersionUID = -7566358804388837978L;

			@Override
			public void actionPerformed(ActionEvent e)
			{
				editorUI.editor.enqueue(new Runnable()
				{
					@Override
					public void run()
					{
						editorUI.clearMap();
					}
				});
			}
		});
		
		fileMenu.add(new AbstractAction("Open[ctrl-O]")
		{
			private static final long serialVersionUID = -7566358804388837978L;

			@Override
			public void actionPerformed(ActionEvent e)
			{
				editorUI.editor.enqueue(new Runnable()
				{
					@Override
					public void run()
					{
						editorUI.open();
					}
				});
			}
		});
		fileMenu.addSeparator();
		fileMenu.add(new AbstractAction("Save[ctrl-S]")
		{
			private static final long serialVersionUID = -7566358804388837978L;

			@Override
			public void actionPerformed(ActionEvent e)
			{
				editorUI.editor.enqueue(new Runnable()
				{
					@Override
					public void run()
					{
						editorUI.save(false);
					}
				});
			}
		});
		fileMenu.add(new AbstractAction("Save As[ctrl-alt-S]")
		{
			private static final long serialVersionUID = -7566358804388837978L;

			@Override
			public void actionPerformed(ActionEvent e)
			{
				editorUI.editor.enqueue(new Runnable()
				{
					@Override
					public void run()
					{
						editorUI.save(true);
					}
				});
			}
		});
		fileMenu.addSeparator();
		fileMenu.add(new AbstractAction("Start game[TAB]")
		{
			private static final long serialVersionUID = -7566358804388837978L;

			@Override
			public void actionPerformed(ActionEvent e)
			{
				editorUI.editor.enqueue(new Runnable()
				{
					@Override
					public void run()
					{
						editorUI.editorFrame.dispatchEvent(new WindowEvent(editorUI.editorFrame, WindowEvent.WINDOW_CLOSING));
					}
				});
			}
		});
		
		editMenu = new JMenu("Edit");
		editMenu.add(new AbstractAction("Undo[ctrl-Z]")
		{
			private static final long serialVersionUID = -7566358804388837978L;

			@Override
			public void actionPerformed(ActionEvent e)
			{
				editorUI.editor.enqueue(new Runnable()
				{
					@Override
					public void run()
					{
						editorUI.editor.undo();
					}
				});
			}
		});
		editMenu.add(new AbstractAction("Redo[ctrl-Y]")
		{
			private static final long serialVersionUID = -550250952409219634L;

			@Override
			public void actionPerformed(ActionEvent e)
			{
				editorUI.editor.enqueue(new Runnable()
				{
					@Override
					public void run()
					{
						editorUI.editor.redo();
					}
				});
			}
		});
		editMenu.addSeparator();
		editMenu.add(new AbstractAction("Delete Selected Object(s)[X]")
		{
			private static final long serialVersionUID = -7566358804388837978L;

			@Override
			public void actionPerformed(ActionEvent e)
			{
				editorUI.editor.enqueue(new Runnable()
				{
					@Override
					public void run()
					{
						editorUI.editor.deleteSelected();
					}
				});
			}
		});
		editMenu.add(new AbstractAction("Select all[ctrl-A]")
		{
			private static final long serialVersionUID = -7566358804388837978L;

			@Override
			public void actionPerformed(ActionEvent e)
			{
				editorUI.editor.enqueue(new Runnable()
				{
					@Override
					public void run()
					{
						editorUI.editor.selectAll(false);
					}
				});
			}
		});
		editMenu.add(new AbstractAction("Select all on screen[A]")
		{
			private static final long serialVersionUID = -7566358804388837978L;

			@Override
			public void actionPerformed(ActionEvent e)
			{
				editorUI.editor.enqueue(new Runnable()
				{
					@Override
					public void run()
					{
						editorUI.editor.selectAll(false);
					}
				});
			}
		});
		editMenu.add(new AbstractAction("Select none[A]")
		{
			private static final long serialVersionUID = -7566358804388837978L;

			@Override
			public void actionPerformed(ActionEvent e)
			{
				editorUI.editor.enqueue(new Runnable()
				{
					@Override
					public void run()
					{
						editorUI.editor.selectNone();
					}
				});
			}
		});
		editMenu.addSeparator();
		editMenu.add(new AbstractAction("Reset Location[alt-G]")
		{
			private static final long serialVersionUID = -7566358804388837978L;

			@Override
			public void actionPerformed(ActionEvent e)
			{
				editorUI.editor.enqueue(new Runnable()
				{
					@Override
					public void run()
					{
						editorUI.editor.reset(Editor2D.MASK_LOCATION);
					}
				});
			}
		});
		editMenu.add(new AbstractAction("Reset Rotation[alt-R]")
		{
			private static final long serialVersionUID = -7566358804388837978L;

			@Override
			public void actionPerformed(ActionEvent e)
			{
				editorUI.editor.enqueue(new Runnable()
				{
					@Override
					public void run()
					{
						editorUI.editor.reset(Editor2D.MASK_ROTATION);
					}
				});
			}
		});
		editMenu.add(new AbstractAction("Reset Scale[alt-S]")
		{
			private static final long serialVersionUID = -7566358804388837978L;

			@Override
			public void actionPerformed(ActionEvent e)
			{
				editorUI.editor.enqueue(new Runnable()
				{
					@Override
					public void run()
					{
						editorUI.editor.reset(Editor2D.MASK_SCALE);
					}
				});
			}
		});
		
		modeMenu = new JMenu("Mode");
		modeMenu.add(paintMode = new JRadioButtonMenuItem(new AbstractAction("Paint[LMB]")
		{
			private static final long serialVersionUID = -7566358804388837978L;

			@Override
			public void actionPerformed(ActionEvent e)
			{
				editorUI.editor.enqueue(new Runnable()
				{
					@Override
					public void run()
					{
						//Nop (default behaviour resets to paint mode)
					}
				});
			}
		}));
		modeMenu.addSeparator();
		modeMenu.add(boxSelectMode = new JRadioButtonMenuItem(new AbstractAction("BoxSelect[B]")
		{
			private static final long serialVersionUID = -7566358804388837978L;

			@Override
			public void actionPerformed(ActionEvent e)
			{
				editorUI.editor.enqueue(new Runnable()
				{
					@Override
					public void run()
					{
						editorUI.editor.setMode(new BoxSelect(editorUI.editor, BoxSelectMode.BOX));
					}
				});
			}
		}));
		modeMenu.add(circleSelectMode = new JRadioButtonMenuItem(new AbstractAction("CircleSelect[B-B]")
		{
			private static final long serialVersionUID = -7566358804388837978L;

			@Override
			public void actionPerformed(ActionEvent e)
			{
				editorUI.editor.enqueue(new Runnable()
				{
					@Override
					public void run()
					{
						editorUI.editor.setMode(new BoxSelect(editorUI.editor, BoxSelectMode.CIRCLE));
					}
				});
			}
		}));
		modeMenu.add(paintSelectMode = new JRadioButtonMenuItem(new AbstractAction("PaintSelect[B-B-B]")
		{
			private static final long serialVersionUID = -7566358804388837978L;

			@Override
			public void actionPerformed(ActionEvent e)
			{
				editorUI.editor.enqueue(new Runnable()
				{
					@Override
					public void run()
					{
						editorUI.editor.setMode(new BoxSelect(editorUI.editor, BoxSelectMode.PAINT));
					}
				});
			}
		}));
		modeMenu.addSeparator();
		modeMenu.add(translateMode = new JRadioButtonMenuItem(new AbstractAction("Grab Selected Object(s)[G]")
		{
			private static final long serialVersionUID = -7566358804388837978L;

			@Override
			public void actionPerformed(ActionEvent e)
			{
				editorUI.editor.enqueue(new Runnable()
				{
					@Override
					public void run()
					{
						editorUI.editor.setMode(new Translate(editorUI.editor, Editor2D.Axes.VIEW, true));
					}
				});
			}
		}));
		modeMenu.add(translateXMode = new JRadioButtonMenuItem(new AbstractAction("Grab Along X[G-X]")
		{
			private static final long serialVersionUID = -7566358804388837978L;

			@Override
			public void actionPerformed(ActionEvent e)
			{
				editorUI.editor.enqueue(new Runnable()
				{
					@Override
					public void run()
					{
						editorUI.editor.setMode(new Translate(editorUI.editor, Editor2D.Axes.X, true));
					}
				});
			}
		}));
		modeMenu.add(translateYMode = new JRadioButtonMenuItem(new AbstractAction("Grab Along Y[G-Y]")
		{
			private static final long serialVersionUID = -7566358804388837978L;

			@Override
			public void actionPerformed(ActionEvent e)
			{
				editorUI.editor.enqueue(new Runnable()
				{
					@Override
					public void run()
					{
						editorUI.editor.setMode(new Translate(editorUI.editor, Editor2D.Axes.Y, true));
					}
				});
			}
		}));
		modeMenu.add(translateLocalXMode = new JRadioButtonMenuItem(new AbstractAction("Grab Along Local X[G-X-X]")
		{
			private static final long serialVersionUID = -7566358804388837978L;

			@Override
			public void actionPerformed(ActionEvent e)
			{
				editorUI.editor.enqueue(new Runnable()
				{
					@Override
					public void run()
					{
						editorUI.editor.setMode(new Translate(editorUI.editor, Editor2D.Axes.LOCAL_X, true));
					}
				});
			}
		}));
		modeMenu.add(translateLocalYMode = new JRadioButtonMenuItem(new AbstractAction("Grab Along Local Y[G-Y-Y]")
		{
			private static final long serialVersionUID = -7566358804388837978L;

			@Override
			public void actionPerformed(ActionEvent e)
			{
				editorUI.editor.enqueue(new Runnable()
				{
					@Override
					public void run()
					{
						editorUI.editor.setMode(new Translate(editorUI.editor, Editor2D.Axes.LOCAL_Y, true));
					}
				});
			}
		}));
		modeMenu.addSeparator();
		modeMenu.add(rotateMode = new JRadioButtonMenuItem(new AbstractAction("Rotate Selected Object(s)[R]")
		{
			private static final long serialVersionUID = -7566358804388837978L;

			@Override
			public void actionPerformed(ActionEvent e)
			{
				editorUI.editor.enqueue(new Runnable()
				{
					@Override
					public void run()
					{
						editorUI.editor.setMode(new Rotate(editorUI.editor, false));
					}
				});
			}
		}));
		modeMenu.add(rotateIndividuallyMode = new JRadioButtonMenuItem(new AbstractAction("Rotate Individually[R-R]")
		{
			private static final long serialVersionUID = -7566358804388837978L;

			@Override
			public void actionPerformed(ActionEvent e)
			{
				editorUI.editor.enqueue(new Runnable()
				{
					@Override
					public void run()
					{
						editorUI.editor.setMode(new Rotate(editorUI.editor, true));
					}
				});
			}
		}));
		modeMenu.addSeparator();
		modeMenu.add(scaleMode = new JRadioButtonMenuItem(new AbstractAction("Scale Selected Objects[S]")
		{
			private static final long serialVersionUID = -7566358804388837978L;

			@Override
			public void actionPerformed(ActionEvent e)
			{
				JPanel scaleBoard = new JPanel();
				scaleBoard.setLayout(new BoxLayout(scaleBoard, BoxLayout.Y_AXIS));
				
				JPanel p = new JPanel();
				p.setLayout(new GridLayout(0, 2));
				
				p.add(new JLabel("Scale factor"));
				StringFormattedEditor<Float> scaleFactorEditor = new StringFormattedEditor<Float>(1.0f);
				p.add(scaleFactorEditor);
				
				p.add(new JLabel("Axes[X, Y]"));
				EnumEditor<Axes> axisEditor = new EnumEditor<Editor2D.Axes>(Editor2D.Axes.VIEW);
				p.add(axisEditor);
				p.add(new JLabel("Scale Mode[S]"));
				EnumEditor<ScaleMode> scaleModeEditor = new EnumEditor<Scale.ScaleMode>(Scale.ScaleMode.SCALE_AND_MOVE); 
				p.add(scaleModeEditor);
				
				scaleBoard.add(p);
				MiscConfigPane scaleConfig = new MiscConfigPane(editorUI);
				scaleBoard.add(scaleConfig);
				
				int r = JOptionPane.showConfirmDialog(null, scaleBoard, "Scale", JOptionPane.OK_CANCEL_OPTION, JOptionPane.PLAIN_MESSAGE);
				if(r == JOptionPane.OK_OPTION)
				{
					editorUI.editor.enqueue(new Runnable()
					{
						@Override
						public void run()
						{
							Scale scale = new Scale(editorUI.editor, scaleModeEditor.getValue(), axisEditor.getValue());
							editorUI.editor.setMode(scale);
							scale.setNumberValue((double)(float)scaleFactorEditor.getValue());
							scale.terminate(false);
						}
				});
				}
			}
		}));
		
		add(fileMenu);
		add(editMenu);
		add(modeMenu);
		
		editorUI.editor.modeListeners.addActionListener(e->updateMode());
		updateMode();
	}

	private void updateMode()
	{
		Mode m = editorUI.editor.mode();
		paintMode.setSelected(m == null || m instanceof Paint);
		boxSelectMode.setSelected(m != null && m instanceof BoxSelect && ((BoxSelect)m).getMode() == BoxSelect.BoxSelectMode.BOX);
		circleSelectMode.setSelected(m != null && m instanceof BoxSelect && ((BoxSelect)m).getMode() == BoxSelect.BoxSelectMode.CIRCLE);
		paintSelectMode.setSelected(m != null && m instanceof BoxSelect && ((BoxSelect)m).getMode() == BoxSelect.BoxSelectMode.PAINT);
		translateMode.setSelected(m != null && m instanceof Translate && ((Translate)m).getAxis() == Editor2D.Axes.VIEW);
		translateXMode.setSelected(m != null && m instanceof Translate && ((Translate)m).getAxis() == Editor2D.Axes.X);
		translateYMode.setSelected(m != null && m instanceof Translate && ((Translate)m).getAxis() == Editor2D.Axes.Y);
		translateLocalXMode.setSelected(m != null && m instanceof Translate && ((Translate)m).getAxis() == Editor2D.Axes.LOCAL_X);
		translateLocalYMode.setSelected(m != null && m instanceof Translate && ((Translate)m).getAxis() == Editor2D.Axes.LOCAL_Y);
		rotateMode.setSelected(m != null && m instanceof Rotate && !((Rotate)m).individualOrigins());
		rotateIndividuallyMode.setSelected(m != null && m instanceof Rotate && ((Rotate)m).individualOrigins());
		scaleMode.setSelected(m != null && m instanceof Scale);
	}

	private static final long serialVersionUID = 5482952363587310458L;	
	
	public void setLocked(boolean b)
	{
		fileMenu.setEnabled(!b);
		editMenu.setEnabled(!b);
	}
}
